﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Ninject.Modules;
using AutoMapper;
using Subtle.Domain.Models;
using Subtle.ViewModels;
using Subtle.Areas.Administration.ViewModels;
using System.IO;

namespace Subtle.Modules
{
	/// <summary>
	/// Auto Mapping Module
	/// </summary>
	public class AutoMappingModule : NinjectModule
	{
		/// <summary>
		/// Load the Auto Mapping Module
		/// </summary>
		public override void Load()
		{
			Mapper.CreateMap<AccountRegisterUserViewModel, User>();
			Mapper.CreateMap<AccountLoginViewModel, User>();
			Mapper.CreateMap<BlogConfigureViewModel, Blog>();
			Mapper.CreateMap<UserConfigureViewModel, User>();

			Mapper.CreateMap<AddPostViewModel, Post>().ForMember(dest => dest.Tags, opt => opt.ResolveUsing<AddTagResolver>());
			Mapper.CreateMap<PostViewModel, Post>().ForMember(dest => dest.Tags, opt => opt.ResolveUsing<AddTagResolver>());

			Mapper.CreateMap<EditPostViewModel, Post>().ForMember(dest => dest.Tags, opt => opt.ResolveUsing<EditAddTagResolver>());
			Mapper.CreateMap<Post, EditPostViewModel>().ForMember(dest => dest.Tags, opt => opt.ResolveUsing<EditTagResolver>());

			Mapper.CreateMap<Post, HomePostViewModel>().ForMember(dest => dest.Tags, opt => opt.ResolveUsing<PostTagResolver>());
			Mapper.CreateMap<Post, PostViewModel>().ForMember(dest => dest.Tags, opt => opt.ResolveUsing<PostTagResolver>());

			Mapper.CreateMap<HomeArchiveViewModel, KeyValuePair<DateTime, int>>();
			Mapper.CreateMap<KeyValuePair<DateTime, int>, HomeArchiveViewModel>()
			.ForMember(dest => dest.Date, opt => opt.ResolveUsing<ArchiveDateResolver>())
			.ForMember(dest => dest.PostCount, opt => opt.ResolveUsing<ArchivePostCountResolver>());

			Mapper.CreateMap<MediaAddViewModel, Media>()
				.ForMember(member => member.Contents, opt => opt.MapFrom(src =>
				{
					byte[] contents = new byte[src.MediaFile.ContentLength];
					src.MediaFile.InputStream.Read(contents, 0, src.MediaFile.ContentLength);
					return contents;
				}))
				.ForMember(member => member.ID, opt => opt.MapFrom(src => { return 0; }))
				.ForMember(member => member.Type, opt => opt.MapFrom(src => src.MediaFile.ContentType))
				.ForMember(member => member.Name, opt => opt.MapFrom(src => src.MediaFile.FileName));
		}

		/// <summary>
		/// Tag Resolver
		/// </summary>
		public class AddTagResolver : ValueResolver<AddPostViewModel, IList<Tag>>
		{
			/// <summary>
			/// Resolve Core
			/// </summary>
			/// <param name="source"></param>
			/// <returns></returns>
			protected override IList<Tag> ResolveCore(AddPostViewModel source)
			{
				return (from tag in source.Tags.Split(',')
						select new Tag() { Description = tag.Trim() }).ToList<Tag>();
			}
		}

		/// <summary>
		/// Edit Tag Resolver
		/// </summary>
		public class EditAddTagResolver : ValueResolver<EditPostViewModel, IList<Tag>>
		{
			/// <summary>
			/// Resolve Core
			/// </summary>
			/// <param name="source"></param>
			/// <returns></returns>
			protected override IList<Tag> ResolveCore(EditPostViewModel source)
			{
				return (from tag in source.Tags.Split(',')
						select new Tag() { Description = tag.Trim() }).ToList<Tag>();
			}
		}

		/// <summary>
		/// Tag Resolver
		/// </summary>
		public class EditTagResolver : ValueResolver<Post, string>
		{
			/// <summary>
			/// Edit Post View Model
			/// </summary>
			/// <param name="source"></param>
			/// <returns></returns>
			protected override string ResolveCore(Post post)
			{
				return String.Join(",", ((from tag in post.Tags
															select tag.Description).ToArray()));
			}
		}

		/// <summary>
		/// Tag Resolver
		/// </summary>
		public class PostTagResolver : ValueResolver<Post, string>
		{
			/// <summary>
			/// Edit Post View Model
			/// </summary>
			/// <param name="source"></param>
			/// <returns></returns>
			protected override string ResolveCore(Post post)
			{
				return String.Join(",", ((from tag in post.Tags
										  select tag.Description).ToArray()));
			}
		}

		/// <summary>
		/// Archive Resolver
		/// </summary>
		public class ArchiveDateResolver : ValueResolver<KeyValuePair<DateTime, int>, string>
		{
			/// <summary>
			/// Resolve Core
			/// </summary>
			/// <param name="source"></param>
			/// <returns></returns>
			protected override string ResolveCore(KeyValuePair<DateTime, int> source)
			{
				return source.Key.Year + "/" + source.Key.Month;
			}
		}

		/// <summary>
		/// Archive Resolver
		/// </summary>
		public class ArchivePostCountResolver : ValueResolver<KeyValuePair<DateTime, int>, int>
		{
			/// <summary>
			/// Resolve Core
			/// </summary>
			/// <param name="source"></param>
			/// <returns></returns>
			protected override int ResolveCore(KeyValuePair<DateTime, int> source)
			{
				return source.Value;
			}
		}
	}
}